﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MT.Enterprise.Utils.Extensions;
using NP.BPMReportPlatform.BPMPlatform;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Engine;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.CourseTrain;
using NP.BPMReportPlatform.CourseTrain.Dtos;
using NP.BPMReportPlatform.Utils;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using SqlSugar;
using Volo.Abp.Application.Dtos;
using NP.Enterprise.Utils.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NP.BPMReportPlatform.UserTrial.Dto;
using NP.BPMReportPlatform.Common.Dtos;
using Microsoft.EntityFrameworkCore;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Mvc;
using Elasticsearch.Net;
using NP.BPMReportPlatform.Document.Dtos;
using NP.BPMReportPlatform.Document;
using NP.BPMReportPlatform.Contract.Dtos;
using NP.BPMReportPlatform.Common;
using NP.BPMReportPlatform.CourseTrain.Enums;
using static NP.BPMReportPlatform.CourseTrain.Dtos.CourseReportDto;
using NPOI.HPSF;
using DotNetCore.CAP.Internal;
using Serilog;

namespace NP.BPMReportPlatform.CourseTrain
{
    /// <summary>
    /// 试用期服务
    /// </summary>
    public class CourseTrainTaskService : BPMReportPlatformAppService, ICourseTrainTaskService
    {
        #region Variables

        private readonly SqlSugarClient _db;
        private readonly SqlSugarClient _dbPlatform;
        private readonly IBPMUtilsAppService _bPMUtilsApp;
        private readonly IBPMPlatformAppService _iBPMPlatformApp;
        private readonly SqlSugarClient _dbEngine;
        private readonly INPRestHttpHelper _nPRestHttp;
        private readonly IDocumentService _documentService;
        private readonly ICommonService _commonService;
        private readonly string _esbWebApiUrl;
        private readonly string _corpid;
        private readonly string _corpsecret;
        private readonly string _uploadUrl;
        private readonly ILogger _logger;

        #endregion

        #region Constructor

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sqlSugarAppService">sqlSugarAppService</param>
        /// <param name="bPMUtilsApp">bPMUtilsApp</param>
        /// <param name="iBPMPlatformApp">iBPMPlatformApp</param>
        /// <param name="httpClient">httpClient</param>
        /// <param name="configuration">configuration</param>
        /// <param name="documentService">documentService</param>
        public CourseTrainTaskService(ISqlSugarAppService sqlSugarAppService, IBPMUtilsAppService bPMUtilsApp
            , IBPMPlatformAppService iBPMPlatformApp, INPRestHttpHelper httpClient, IConfiguration configuration,
            IDocumentService documentService, ICommonService commonService, ILogger logger)
        {
            _db = sqlSugarAppService.GetBusinessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _dbEngine = sqlSugarAppService.GetEngineInstance();
            _bPMUtilsApp = bPMUtilsApp;
            _iBPMPlatformApp = iBPMPlatformApp;
            _nPRestHttp = httpClient;
            _documentService = documentService;
            _commonService = commonService;
            _esbWebApiUrl = configuration["ILearningSettings:ilearningCommonApi"];
            _corpid = configuration["ILearningSettings:corpid"];
            _corpsecret = configuration["ILearningSettings:corpsecret"];
            _uploadUrl = configuration["BPM:AttachmentUpLoadUrl"];
            _logger = logger;
        }

        #endregion

        #region 获取培训任务单数据

        /// <summary>
        /// 培训任务单列表明细查询数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns>培训任务单列表</returns>
        public async Task<PagedResultPowerDto<GetTrainTaskOutput>> GetTrainTaskListResult(GetTrainResultInput input)
        {
            RefAsync<int> totalCount = 0;
            // 权限过滤
            var currentWorkNumber = CurrentUser != null && CurrentUser.UserName != null ? CurrentUser.UserName : string.Empty;
            var role = getUserRoles(currentWorkNumber);
            var result = new PagedResultPowerDto<GetTrainTaskOutput>();
            result.IsAdmin = input.IsAdmin || role.Item1;
            result.IsHRBP = role.Item2;
            var listQueryable = _db.Queryable<CourseTrainTaskEntity>()
                  .WhereIF(input.TraginEndStartDate != null, t => input.TraginEndStartDate <= t.EndTime)
                  .WhereIF(input.TraginEndEndDate != null, t => input.TraginEndEndDate >= t.EndTime)
                  .WhereIF(input.TraginBeginStartDate != null, t => input.TraginBeginStartDate <= t.BeginTime)
                  .WhereIF(input.TraginBeginEndDate != null, t => input.TraginBeginEndDate >= t.BeginTime)
                  .WhereIF(!string.IsNullOrEmpty(input.InstanceNumber), t => t.InstanceNumber.Contains(input.InstanceNumber))
                  .WhereIF(!string.IsNullOrEmpty(input.Project), t => t.TraningProject == input.Project)
                  .WhereIF(!string.IsNullOrEmpty(input.TrainDate), t => t.TrainDate.Value.ToString("yyyy-MM") == input.TrainDate)
                  .WhereIF(!string.IsNullOrEmpty(input.CourseName), t => t.CourseName.Contains(input.CourseName))
                  .WhereIF(!string.IsNullOrEmpty(input.CourseType), t => t.CourseType == input.CourseType)
                  .WhereIF(!string.IsNullOrEmpty(input.TechMethod), t => t.TechMethod == input.TechMethod)
                  .WhereIF(!string.IsNullOrEmpty(input.TraningTarget), t => t.TraningTarget == input.TraningTarget)
                  .WhereIF(!string.IsNullOrEmpty(input.WorkNumber), t => t.WorkNumber.Contains(input.WorkNumber))
                  .WhereIF(!string.IsNullOrEmpty(input.UserName), t => t.CreateUserName.Contains(input.UserName))
                  .WhereIF(!string.IsNullOrEmpty(input.Instructor), t => t.Instructor.Contains(input.Instructor))
                  .WhereIF(!string.IsNullOrEmpty(input.TrainCode), t => t.CourseTrainCode.Contains(input.TrainCode))
                  .WhereIF(!result.IsAdmin, t => currentWorkNumber == t.WorkNumber || (result.IsHRBP && role.Item4.Contains(t.WorkNumber)))
                  .OrderBy(t => new { t.InstanceNumber }, OrderByType.Desc)
                  .OrderBy(t => new { t.CourseTrainCode }, OrderByType.Asc)
                .Select(t =>
                    new GetTrainTaskOutput()
                    {
                        CourseTrainTaskId = t.CourseTrainTaskId,
                        InstanceNumber = t.InstanceNumber,
                        CourseTrainCode = t.CourseTrainCode,
                        ILearningCode = t.ILearningCode,
                        CreateUserName = t.CreateUserName,
                        CreateUserWorkNumber = t.WorkNumber,
                        StatusName = t.StatusName,
                        Company = t.Company,
                        DepartMent = t.Department,
                        TrainDate = t.TrainDate,
                        ProjectName = t.TraningProject,
                        TrainUserBudget = t.TrainUserBudget,
                        CoursePeriod = t.CoursePeriod,
                        TrainUserNumber = t.TrainUserNumber,
                        Instructor = t.Instructor,
                        BeginTime = t.BeginTime,
                        EndTime = t.EndTime,
                        IfAllowance = t.IfAllowance,
                        IsObtainCert = t.IsObtainCert,
                        CourseType = t.CourseType,
                        TechMethod = t.TechMethod,
                        CourseName = t.CourseName,
                        TraningTarget = t.TraningTarget
                    });

            var listViewDto = await listQueryable.ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            result.TotalCount = totalCount;
            result.Items = listViewDto;
            return result;
        }

        /// <summary>
        /// 获取任务单详情信息
        /// </summary>
        /// <param name="courseTrainTaskId">任务单号</param>
        /// <returns>任务单详情</returns>
        public async Task<CourseTrainTaskDto> GetCourseTrainTaskData(string courseTrainTaskId)
        {
            CourseTrainTaskDto courseTrainTaskDto = new CourseTrainTaskDto();
            courseTrainTaskDto.BaseData = await _db.Queryable<CourseTrainTaskEntity>().FirstAsync(t => t.CourseTrainTaskId == courseTrainTaskId);
            courseTrainTaskDto.ILearningList = await _db.Queryable<CourseILearningReleationShipEntity>().Where(t => t.CourseTrainTaskId == courseTrainTaskId).OrderBy(t => t.No).ToListAsync();
            courseTrainTaskDto.TrainUserList = await _db.Queryable<CourseTrainUserDetailEntity>().Where(t => t.CourseTrainTaskId == courseTrainTaskId).OrderBy(t => t.No).ToListAsync();
            courseTrainTaskDto.PointAllocateList = await _db.Queryable<CourseTrainPeriodEntity>().Where(t => t.CourseTrainTaskId == courseTrainTaskId).OrderBy(t => t.No).ToListAsync();
            return courseTrainTaskDto;
        }

        /// <summary>
        /// 提交任务单数据
        /// </summary>
        /// <param name="data">请求参数</param>
        /// <param name="isSubmit">是否提交</param>
        /// <returns>返回消息</returns>
        public async Task<(bool Result, string Msg)> CourseTrainTaskSave(CourseTrainTaskDto data, bool isSubmit)
        {
            var result = CheckTrainTask(data);
            if (isSubmit && !result.Result)
            {
                return result;
            }

            if (isSubmit)
            {
                data.BaseData.Status = CourseTrainTaskStatusEnum.培训完成.GetHashCode();
                data.BaseData.StatusName = CourseTrainTaskStatusEnum.培训完成.ToString();
            }

            int i = 1;

            data.BaseData.ActrualUsers = data.TrainUserList.Count;
            data.ILearningList?.ForEach(t =>
            {
                t.CourseILearningReleationId = Guid.NewGuid().ToString();
                t.CourseTrainCode = data.BaseData.CourseTrainCode;
                t.CourseTrainId = data.BaseData.CourseTrainId;
                t.CourseTrainTaskId = data.BaseData.CourseTrainTaskId;
                t.No = i;
                i++;
            });

            DateTime today = DateTime.Now;
            string syncDate = today.ToString("yyyy-M");
            i = 1;
            data.TrainUserList?.ForEach(t =>
            {
                t.CourseTrainUserDetailId = Guid.NewGuid().ToString();
                t.CourseTrainCode = data.BaseData.CourseTrainCode;
                t.CourseTrainId = data.BaseData.CourseTrainId;
                t.CourseTrainTaskId = data.BaseData.CourseTrainTaskId;
                t.InstanceNumber = data.BaseData.InstanceNumber;
                t.TraningProject = data.BaseData.TraningProject;
                t.CourseName = data.BaseData.CourseName;
                t.CreateWorkNumber = data.BaseData.WorkNumber;
                t.IsObtainCert = data.BaseData.IsObtainCert ?? false; // 是否需要培训证书
                t.No = i;

                if (data.BaseData.Status == CourseTrainTaskStatusEnum.培训完成.GetHashCode())
                {
                    t.CompleteDate = today;

                    if (t.IsObtainCert == false)
                    {
                        t.ThridSyncDate = syncDate;
                    }
                }

                i++;
            });

            i = 1;
            data.PointAllocateList?.ForEach(t =>
            {
                t.CourseTrainPeriodId = Guid.NewGuid().ToString();
                t.CourseTrainId = data.BaseData.CourseTrainId;
                t.CourseTrainTaskId = data.BaseData.CourseTrainTaskId;
                t.No = i;
                i++;
            });

            await _db.Deleteable<CourseILearningReleationShipEntity>().Where(t => t.CourseTrainTaskId == data.BaseData.CourseTrainTaskId).ExecuteCommandAsync();
            await _db.Deleteable<CourseTrainUserDetailEntity>().Where(t => t.CourseTrainTaskId == data.BaseData.CourseTrainTaskId).ExecuteCommandAsync();
            await _db.Deleteable<CourseTrainPeriodEntity>().Where(t => t.CourseTrainTaskId == data.BaseData.CourseTrainTaskId).ExecuteCommandAsync();


            await _db.Saveable(data.ILearningList).ExecuteCommandAsync();
            await _db.Saveable(data.TrainUserList).ExecuteCommandAsync();
            await _db.Saveable(data.PointAllocateList).ExecuteCommandAsync();

            data.BaseData.ILearningCode = data.ILearningList.Select(t => t.ILearningCode)?.JoinAsString(",");
            data.BaseData.TrainUserNumber = data.TrainUserList.IsNullOrEmpty() ? 0 : data.TrainUserList.Count();

            await _db.Saveable(data.BaseData).ExecuteCommandAsync();

            if (isSubmit)
            {
                // 国内单据提交后更新导师工时
                data.PointAllocateList?.ForEach(async item =>
                {
                    decimal poroid = await _db.Queryable<CourseTrainPeriodEntity, CourseTrainTaskEntity>((p, t) => p.CourseTrainTaskId == t.CourseTrainTaskId)
                    .Where((p, t) => t.Status == 4 && p.InstructorCode == item.InstructorCode)
                    .SumAsync((p, t) => p.CoursePeriod ?? 0m);
                    await _db.Updateable<CourseInstructorEntity>().SetColumns(t => t.CoursePeriod == poroid).Where(t => t.InstructorCode == item.InstructorCode).ExecuteCommandAsync();
                });
            }

            return (true, string.Empty);
        }

        /// <summary>
        /// 变更任务单状态
        /// </summary>
        /// <param name="id">id</param>
        /// <param name="status">status</param>
        /// <returns>返回消息</returns>
        public async Task UpdateStatus(string id, int status)
        {
            CourseTrainTaskStatusEnum statusEnum;
            switch (status)
            {
                case -1:
                    statusEnum = CourseTrainTaskStatusEnum.终止;
                    break;
                case 4:
                    statusEnum = CourseTrainTaskStatusEnum.培训完成;
                    break;
                default:
                    statusEnum = CourseTrainTaskStatusEnum.处理中;
                    break;
            }

            string statusName = statusEnum.GetStringValue();

            await _db.Updateable<CourseTrainTaskEntity>().SetColumns(t => t.Status == status).SetColumns(t => t.StatusName == statusName).Where(t => t.CourseTrainTaskId == id).ExecuteCommandAsync();
        }

        /// <summary>
        /// 报销获取培训人员信息接口
        /// </summary>
        /// <returns></returns>
        public async Task<TrainingMasterDataDto.ResponseDto> GetReimbursementTrainUser(TrainingMasterDataDto.RequestDto request)
        {
            _logger.Information($"报销获取培训人员信息接口，GetReimbursementTrainUser，{JsonConvert.SerializeObject(request)}");

            TrainingMasterDataDto.ResponseDto response = new TrainingMasterDataDto.ResponseDto();
            try
            {
                DateTime dateTime;
                if (DateTime.TryParseExact(request.StrYearMonth, request.StrYearMonth.Length == 6 ? "yyyy-M" : "yyyy-MM", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
                {
                    Console.WriteLine(dateTime.ToString("yyyy-MM-dd"));
                    request.StrYearMonth = dateTime.ToString("yyyy-M");
                }
                else
                {
                    response.Result = $"无法解析日期字符串{request.StrYearMonth}";
                    return response;
                }

                var result = _db.Queryable<CourseTrainTaskEntity, CourseTrainUserDetailEntity>((t, d) => t.CourseTrainTaskId == d.CourseTrainTaskId).
                Where((t, d) => d.ThridSyncDate == request.StrYearMonth)
                .Where((t, d) => t.Status == CourseTrainTaskStatusEnum.培训完成.GetHashCode())
                .OrderBy((t, d) => t.CourseTrainCode)
                .Select((t, d) => new { t.InstanceNumber, t.CourseTrainCode, t.CourseName, t.BeginTime, t.EndTime, d.IfAllowance, d.TrainUserWorknumber, d.MealFrequency });
                var ttt = await result.ToListAsync();
                if (ttt.IsNullOrEmpty())
                {
                    response.Result = $"未找到{request.StrYearMonth}培训年月的培训项目数据";
                    return response;
                }
                else
                {
                    response.Result = "OK";
                    response.Msg = ttt.Count.ToString();
                    foreach (var item in ttt)
                    {
                        response.IdList.Add(item.InstanceNumber + "-" + item.TrainUserWorknumber);
                        response.TIdList.Add(item.CourseTrainCode);
                        response.NameList.Add(item.CourseName);
                        response.TTimeList.Add(item.BeginTime.Value.ToString("yyyy/MM/dd") + "至" + item.EndTime.Value.ToString("yyyy/MM/dd"));
                        response.YCCSList.Add(item.MealFrequency.ToString());
                        response.CLJT_LIST.Add(item.IfAllowance == true ? "是" : "否");
                        response.EIdList.Add(item.TrainUserWorknumber);
                    }
                }

            }
            catch (Exception e)
            {
                response.Result = e.Message;
            }

            return response;
        }

        /// <summary>
        /// RISK获取培训人员信息接口
        /// </summary>
        /// <returns></returns>
        public TrainTaskInfoDto GetTrainTaskInfo(string id)
        {
            _logger.Information($"RISK获取培训人员信息接口，GetTrainTaskInfo，{id}");

            var result = _db.Queryable<CourseTrainTaskEntity, CourseTrainEntity>((t, c) => t.CourseTrainId == c.CourseTrainId)
                  .Where((t, c) => t.CourseTrainCode == id)
                  .Select((t, c) => new TrainTaskInfoDto
                  {
                      Company = t.Company,
                      Year = t.TrainDate.Value.Year.ToString(),
                      Month = t.TrainDate.Value.Month.ToString(),
                      Project = t.TraningProject,
                      Target = t.TraningTarget,
                      Number = t.TrainUserNumber,
                      Budget = t.TrainUserBudget,
                      Reason = c.Reason
                  })
                  .First();

            if (result == null)
            {
                var overEntity = _db.Queryable<CourseOverSeaTrainEntity>().First(t => t.CourseTrainCode == id);
                if (overEntity != null)
                {
                    var overDetails = _db.Queryable<CourseOverSeaTrainDetailEntity>().Where(t => t.InstanceNumber == overEntity.InstanceNumber).ToList();
                    var userEx = _dbPlatform.Queryable<UserExtension, CorporateEntity>((t, c) => t.Sapcompanycode == c.CorporateCode).Where((t, c) => t.Sapemployeeid == overEntity.DispatchWorkNumber).Select((t, c) => c)?.First();
                    result = new TrainTaskInfoDto();
                    result.Company = userEx?.CorporateName;
                    result.Year = overDetails.Min(t => t.BeginTime?.Year).ToString();
                    result.Month = overDetails.Min(t => t.BeginTime?.Month).ToString();
                    result.Project = $"{overEntity.DispatchUserName}的海外培训计划";
                    result.Target = overEntity.Target;
                    result.Number = 1;
                    result.Reason = overEntity.Reason;
                    result.Budget = overEntity.TotalCost;
                }
            }

            return result;
        }
        #endregion
        #region 海外培训任务单
        /// <summary>
        /// 海外培训任务单列表明细查询数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns>培训任务单列表</returns>
        public async Task<PagedResultPowerDto<GetTrainOverSeaOutput>> GetTrainOverSeaListResult(GetTrainResultInput input)
        {
            RefAsync<int> totalCount = 0;
            // 权限过滤
            var currentWorkNumber = CurrentUser != null && CurrentUser.UserName != null ? CurrentUser.UserName : string.Empty;
            var role = getUserRoles(currentWorkNumber);
            var result = new PagedResultPowerDto<GetTrainOverSeaOutput>();
            result.IsAdmin = role.Item1;
            result.IsHRBP = role.Item2;
            var listQueryable = _db.Queryable<CourseOverSeaTrainEntity>()
                  .WhereIF(!string.IsNullOrEmpty(input.InstanceNumber), t => t.InstanceNumber.Contains(input.InstanceNumber) || t.ChangeInstanceNumber.Contains(input.InstanceNumber))
                  .WhereIF(!string.IsNullOrEmpty(input.WorkNumber), t => t.DispatchWorkNumber.Contains(input.WorkNumber))
                  .WhereIF(!string.IsNullOrEmpty(input.UserName), t => t.DispatchUserName.Contains(input.UserName))
                  .WhereIF(!result.IsAdmin, t => currentWorkNumber == t.DispatchWorkNumber || currentWorkNumber == t.WorkNumber ||
                  (result.IsHRBP && role.Item4.Contains(t.DispatchWorkNumber))
                  )
                  .Select(t =>
                    new GetTrainOverSeaOutput()
                    {
                        CourseTrainId = t.CourseTrainId,
                        InstanceNumber = t.InstanceNumber,
                        CourseTrainCode = t.CourseTrainCode,
                        ChangeInstanceNumber = t.ChangeInstanceNumber,
                        CourseAddress = t.CourseAddress,
                        CreateUserName = t.CreateUserName,
                        CreateUserWorkNumber = t.WorkNumber,
                        DispatchUserName = t.DispatchUserName,
                        DispatchWorkNumber = t.DispatchWorkNumber,
                        StatusName = t.StatusName,
                        PassprotNumber = t.PassprotNumber,
                        TotalCost = t.TotalCost
                    }).OrderBy(t => t.InstanceNumber, OrderByType.Desc);

            var listViewDto = await listQueryable.ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            // 如果是导出的话，就不用搜索总结数据
            if (input.PageSize != int.MaxValue)
            {
                var courseTrainIds = listViewDto.Select(t => t.CourseTrainId).ToList();
                var summars = await _db.Queryable<CourseSummaryEntity>().Where(t => courseTrainIds.Contains(t.CourseTrainId) && t.SummaryType == 2).ToListAsync();
                foreach (var item in listViewDto)
                {
                    var summarCHild = summars.Where(t => t.CourseTrainId == item.CourseTrainId).FirstOrDefault();
                    if (summarCHild != null)
                    {
                        item.SummarData = summarCHild;
                    }
                }
            }

            result.TotalCount = totalCount;
            result.Items = listViewDto;
            return result;
        }

        /// <summary>
        /// 获取海外任务单详情信息
        /// </summary>
        /// <param name="courseId">任务单号</param>
        /// <returns>任务单详情</returns>
        public async Task<CourseOverSeaDto> GetCourseOverSeaData(string courseId)
        {
            CourseOverSeaDto courseTrainTaskDto = new CourseOverSeaDto();
            courseTrainTaskDto.BaseData = await _db.Queryable<CourseOverSeaTrainEntity>().InSingleAsync(courseId);
            courseTrainTaskDto.TrainDetails = await _db.Queryable<CourseOverSeaTrainDetailEntity>().Where(t => t.InstanceNumber == courseTrainTaskDto.BaseData.InstanceNumber).OrderBy(t => t.KeyIndex).ToListAsync();
            var summars = await _db.Queryable<CourseSummaryEntity>().Where(t => t.CourseTrainId == courseId).ToListAsync();
            courseTrainTaskDto.Summary = summars?.FirstOrDefault(t => t.SummaryType == 2) ?? new CourseSummaryEntity();
            courseTrainTaskDto.Experience = summars?.Where(t => t.SummaryType == 1)?.OrderBy(t => t.KeyIndex).ToList() ?? new List<CourseSummaryEntity>();
            return courseTrainTaskDto;
        }

        /// <summary>
        /// 变更海外任务单状态
        /// </summary>
        /// <param name="id">id</param>
        /// <param name="status">status</param>
        /// <returns>返回消息</returns>
        public async Task<(bool Result, string Msg)> UpdateOverSeaStatus(string id, int status)
        {
            CourseTrainTaskStatusEnum statusEnum;
            switch (status)
            {
                case -1:
                    statusEnum = CourseTrainTaskStatusEnum.终止;
                    break;
                case 4:
                    int count = await _db.Queryable<CourseSummaryEntity>().Where(t => t.CourseTrainId == id && t.SummaryType == 2).CountAsync();
                    if (count == 0)
                    {
                        return (false, "必须先填写培训总结");
                    }
                    await _db.Updateable<CourseSyncTaskEntity>().SetColumns(t => t.Status == 0).Where(t => t.CourseTrainId == id).ExecuteCommandAsync();
                    statusEnum = CourseTrainTaskStatusEnum.培训完成;
                    break;
                default:
                    statusEnum = CourseTrainTaskStatusEnum.处理中;
                    break;
            }

            string statusName = statusEnum.GetStringValue();
            await _db.Updateable<CourseOverSeaTrainEntity>().SetColumns(t => t.Status == status).SetColumns(t => t.StatusName == statusName).Where(t => t.CourseTrainId == id).ExecuteCommandAsync();
            return (true, "");
        }

        /// <summary>
        /// 更新护照信息
        /// </summary>
        /// <param name="id">id</param>
        /// <param name="value">号码</param>
        /// <returns>返回消息</returns>
        public async Task<(bool Result, string Msg)> UpdatePortNumber(string id, string value)
        {
            await _db.Updateable<CourseOverSeaTrainEntity>().SetColumns(t => t.PassprotNumber == value).Where(t => t.CourseTrainId == id).ExecuteCommandAsync();
            return (true, "");
        }
        #endregion
        #region 培训考证管理
        /// <summary>
        /// 获取培训考证列表数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns>培训考证列表数据</returns>
        public async Task<PagedResultPowerDto<GetCourseCertOutput>> GetCourseCertListResult(GetTrainResultInput input)
        {
            RefAsync<int> totalCount = 0;
            var currentWorkNumber = CurrentUser != null && CurrentUser.UserName != null ? CurrentUser.UserName : string.Empty;
            var role = getUserRoles(currentWorkNumber);
            var result = new PagedResultPowerDto<GetCourseCertOutput>();
            result.IsAdmin = role.Item1;
            result.IsHRBP = role.Item2;
            result.IsHRBPHead = role.Item3;

            var listQueryable = _db.Queryable<CourseTrainUserDetailEntity, CourseTrainTaskEntity>((t, p) => t.CourseTrainTaskId == p.CourseTrainTaskId)
                  .WhereIF(!input.Project.IsNullOrEmpty(), (t, p) => t.TraningProject.Contains(input.Project))
                  .WhereIF(!input.WorkNumber.IsNullOrEmpty(), (t, p) => t.TrainUserWorknumber.Contains(input.WorkNumber))
                  .WhereIF(!input.UserName.IsNullOrEmpty(), (t, p) => t.TrainUser.Contains(input.UserName))
                  .WhereIF(!input.InstanceNumber.IsNullOrEmpty(), (t, p) => t.InstanceNumber.Contains(input.InstanceNumber))
                  .WhereIF(!(result.IsAdmin || result.IsHRBPHead), (t, p) => currentWorkNumber == t.TrainUserWorknumber || (result.IsHRBP && role.Item4.Contains(t.TrainUserWorknumber)))
                  .Where((t, p) => t.IsObtainCert == true && p.Status == CourseTrainTaskStatusEnum.培训完成.GetHashCode())
                  .OrderBy(t => new { t.InstanceNumber, t.No }, OrderByType.Desc)
                .Select((t, p) =>
                    new GetCourseCertOutput()
                    {
                        CourseTrainUserDetailId = t.CourseTrainUserDetailId,
                        InstanceNumber = t.InstanceNumber,
                        CourseTrainCode = t.CourseTrainCode,
                        TrainUser = t.TrainUser,
                        TrainUserWorknumber = t.TrainUserWorknumber,
                        TraningProject = t.TraningProject,
                        CourseName = t.CourseName,
                        CertEndDate = t.CertEndDate,
                        CertId = t.CertId,
                        CertName = t.CertName,
                        Status = t.CertStatus ?? 0,
                        WorkNumber = p.WorkNumber
                    });

            var listViewDto = await listQueryable.ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            result.TotalCount = totalCount;
            result.Items = listViewDto;
            return result;
        }

        /// <summary>
        /// 上传证书文件
        /// </summary>
        /// <param name="bytes">bytes</param>
        /// <param name="fileName">文件名称</param>
        /// <param name="courseTrainUserDetailId">明细id</param>
        /// <returns></returns>

        public async Task<(bool Result, string Msg)> UploadCert(byte[] bytes, string fileName, string courseTrainUserDetailId)
        {
            var result = await _documentService.Upload(bytes, fileName);
            if (!result.Result)
            {
                return result;
            }

            List<DocumentDto> documents = JsonConvert.DeserializeObject<List<DocumentDto>>(result.Msg);
            string docId = documents.FirstOrDefault().DocumentId;

            await _db.Updateable<CourseTrainUserDetailEntity>()
                 .SetColumns(t => t.CertName == fileName)
                 .SetColumns(t => t.CertId == docId).Where(t => t.CourseTrainUserDetailId == courseTrainUserDetailId)
                 .ExecuteCommandAsync();

            return (true, result.Msg);
        }

        /// <summary>
        /// 更新证书状态
        /// </summary>
        /// <param name="status">状态</param>
        /// <param name="courseTrainUserDetailId">明细id</param>
        /// <returns></returns>
        public async Task CertUpdateStatus(string courseTrainUserDetailId, int status)
        {
            DateTime today = DateTime.Now;
            string syncDate = today.ToString("yyyy-M");
            await _db.Updateable<CourseTrainUserDetailEntity>()
             .SetColumns(t => t.CertStatus == status)
             .SetColumns(t => t.ApproveDate == today)
             .SetColumns(t => t.ThridSyncDate == syncDate)
             .Where(t => t.CourseTrainUserDetailId == courseTrainUserDetailId)
             .ExecuteCommandAsync();
        }

        /// <summary>
        /// 更新证书截止日期
        /// </summary>
        /// <param name="endDate">截止日期</param>
        /// <param name="courseTrainUserDetailId">明细id</param>
        public async Task CertEndDate(string courseTrainUserDetailId, DateTime endDate)
        {
            await _db.Updateable<CourseTrainUserDetailEntity>()
             .SetColumns(t => t.CertEndDate == endDate).Where(t => t.CourseTrainUserDetailId == courseTrainUserDetailId)
             .ExecuteCommandAsync();
        }

        /// <summary>
        /// 提交培训心得，总结
        /// </summary>
        /// <param name="summaryDto">任务单号</param>
        /// <returns></returns>
        public async Task<(bool Result, string Msg)> SummarySubmit(CourseSummaryEntity summaryDto)
        {
            if (summaryDto.CourseSummaryId.IsNullOrEmpty())
            {
                summaryDto.CourseSummaryId = Guid.NewGuid().ToString();
                summaryDto.CreateTime = DateTime.Now;
                await _db.Insertable(summaryDto).ExecuteCommandAsync();
            }
            else
            {
                await _db.Updateable(summaryDto).ExecuteCommandAsync();
            }

            return (true, string.Empty);
        }
        #endregion
        #region 讲师页面

        /// <summary>
        /// 讲师列表明细查询数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns>讲师列表明细查询数据</returns>
        public async Task<PagedResultPowerDto<GetCourseInstructorOutput>> GetCourseInstructorList(GetCourseItemInput input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = _db.Queryable<CourseInstructorEntity>()
                  .WhereIF(!input.Code.IsNullOrEmpty(), t => t.UserId.Contains(input.Code))
                  .WhereIF(!input.Name.IsNullOrEmpty(), t => t.InstructorName.Contains(input.Name))
                  .OrderBy(t => t.InstructorCode, OrderByType.Desc)
                .Select(t =>
                    new GetCourseInstructorOutput()
                    {
                        CourseInstructorId = t.CourseInstructorId,
                        InstructorCode = t.InstructorCode,
                        UserLoginId = t.UserId,
                        InstructorType = t.InstructorType,
                        InstructorName = t.InstructorName,
                        Company = t.Company,
                        CoursePeriod = t.CoursePeriod,
                        Status = t.Status
                    });

            var listViewDto = await listQueryable.ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            //返回结果
            return new PagedResultPowerDto<GetCourseInstructorOutput>()
            {
                TotalCount = totalCount,
                Items = listViewDto
            };
        }

        /// <summary>
        /// 讲师项目使用情况明细查询数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns>讲师项目使用情况明细查询数据</returns>
        public async Task<PagedResultPowerDto<GetInstructorUseSummaryOutput>> GetCourseInstructorUseList(GetTrainResultInput input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = _db.Queryable<CourseTrainTaskEntity, CourseTrainPeriodEntity>((t, i) => t.CourseTrainTaskId == i.CourseTrainTaskId)
                  .Where((t, i) => t.Status == 4)
                 .WhereIF(!input.Instructor.IsNullOrEmpty(), (t, i) => i.InstructorName.Contains(input.Instructor) || i.InstructorWorknumber.Contains(input.Instructor))
                 .WhereIF(!input.CourseName.IsNullOrEmpty(), (t, i) => t.CourseName.Contains(input.CourseName))
                 .WhereIF(!input.Project.IsNullOrEmpty(), (t, i) => t.TraningProject.Contains(input.Project))
                  .OrderBy((t, i) => t.CreateTime, OrderByType.Desc)
                .Select((t, i) =>
                    new GetInstructorUseSummaryOutput()
                    {
                        TraningProject = t.TraningProject,
                        InstructorCode = i.InstructorWorknumber,
                        CourseTrainCode = t.CourseTrainCode,
                        InstructorName = i.InstructorName,
                        CourseName = t.CourseName,
                        CoursePeriod = i.CoursePeriod,
                    });

            var listViewDto = await listQueryable.ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            //返回结果
            return new PagedResultPowerDto<GetInstructorUseSummaryOutput>()
            {
                TotalCount = totalCount,
                Items = listViewDto
            };
        }

        /// <summary>
        /// 培训讲师使用明细数据 导出数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<GetInstructorUseSummaryOutput>> ExportCourseInstructorUseListAsync(GetTrainResultInput input)
        {
            var listQueryable = _db.Queryable<CourseTrainTaskEntity, CourseTrainPeriodEntity>((t, i) => t.CourseTrainTaskId == i.CourseTrainTaskId)
                 .Where((t, i) => t.Status == 4)
                 .WhereIF(!input.Instructor.IsNullOrEmpty(), (t, i) => i.InstructorName.Contains(input.Instructor) || i.InstructorWorknumber.Contains(input.Instructor))
                 .WhereIF(!input.CourseName.IsNullOrEmpty(), (t, i) => t.CourseName.Contains(input.CourseName))
                 .WhereIF(!input.Project.IsNullOrEmpty(), (t, i) => t.TraningProject.Contains(input.Project))
                 .OrderBy((t, i) => t.CreateTime, OrderByType.Desc)
               .Select((t, i) =>
                   new GetInstructorUseSummaryOutput()
                   {
                       TraningProject = t.TraningProject,
                       InstructorCode = i.InstructorWorknumber,
                       CourseTrainCode = t.CourseTrainCode,
                       InstructorName = i.InstructorName,
                       CourseName = t.CourseName,
                       CoursePeriod = i.CoursePeriod,
                   });
            return await listQueryable.ToListAsync();
        }

        /// <summary>
        /// 新增或者更新培训讲师数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task AddOrUpdateCourseInstructor(CourseInstructorEntity input)
        {
            if (input.CourseInstructorId.IsNullOrEmpty())
            {
                input.CourseInstructorId = Guid.NewGuid().ToString();
                input.CreateDate = DateTime.Now;
                input.CreateUser = CurrentUser.UserName;
                input.CreateUser = CurrentUser.Id.ToString();
                input.Status = 1;

                int count = await _db.Queryable<CourseInstructorEntity>().Where(t => t.InstructorCode == input.InstructorCode).CountAsync();

                if (count > 0)
                {
                    throw new Exception($"{input.InstructorCode}编码已存在！");
                }

                await _db.Insertable(input).ExecuteCommandAsync();
            }
            else
            {
                int count = await _db.Queryable<CourseInstructorEntity>().Where(t => t.InstructorCode == input.InstructorCode && t.CourseInstructorId != input.CourseInstructorId).CountAsync();

                if (count > 0)
                {
                    throw new Exception($"{input.InstructorCode}编码已存在！");
                }

                await _db.Updateable(input).ExecuteCommandAsync();
            }
        }

        /// <summary>
        /// 更新培训讲师状态
        /// </summary>
        /// <param name="courseInstructorId">主键</param>
        /// <param name="status">状态</param>
        public async Task UpdateCourseInstructorStatus(string courseInstructorId, int status)
        {
            await _db.Updateable<CourseInstructorEntity>().SetColumns(t => t.Status == status).Where(t => t.CourseInstructorId == courseInstructorId).ExecuteCommandAsync();
        }


        /// <summary>
        /// 删除培训讲师数据
        /// </summary>
        /// <param name="courseInstructorId">主键</param>
        public async Task DeleteCourseInstructor(string courseInstructorId)
        {
            await _db.Deleteable<CourseInstructorEntity>().Where(t => t.CourseInstructorId == courseInstructorId).ExecuteCommandAsync();
        }

        /// <summary>
        /// 培训讲师数据 导出数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<GetCourseInstructorOutput>> ExportCourseInstructorResultAsync(GetCourseItemInput input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = _db.Queryable<CourseInstructorEntity>()
                  .WhereIF(!input.Code.IsNullOrEmpty(), t => t.UserId.Contains(input.Code))
                  .WhereIF(!input.Name.IsNullOrEmpty(), t => t.InstructorName.Contains(input.Name))
                  .OrderBy(t => t.UserId, OrderByType.Asc)
                .Select(t =>
                    new GetCourseInstructorOutput()
                    {
                        CourseInstructorId = t.CourseInstructorId,
                        InstructorCode = t.InstructorCode,
                        UserLoginId = t.UserId,
                        InstructorType = t.InstructorType,
                        InstructorName = t.InstructorName,
                        Company = t.Company,
                        CoursePeriod = t.CoursePeriod,
                        Status = t.Status
                    });

            var listViewDto = await listQueryable.ToListAsync();

            //返回结果
            return listViewDto;
        }

        /// <summary>
        /// 获取讲师下拉选项
        /// </summary>
        public async Task<List<ItemPairDto>> GetInstructorOptions()
        {
            return await _db.Queryable<CourseInstructorEntity>()
                .Where(t => t.Status == 1)
                .Where("InstructorType='内部讲师' or (Company is not null and Company!='')")
                .Select(t => new ItemPairDto { Value = t.InstructorCode, ExtendFiled2 = t.WorkNumber, Label = t.InstructorName, ExtendFiled = t.Company, ExtendFiled1 = t.InstructorType })
                .ToListAsync();
        }

        /// <summary>
        /// 根据工号获取培训人员明细数据
        /// </summary>
        /// <param name="worknumbers">请求参数</param>
        /// <returns>培训人员明细数据</returns>
        public async Task<List<CourseTrainUserDetailEntity>> GetUserInfo(List<string> worknumbers)
        {
            var users = await _dbPlatform.Queryable<Users>().Where(t => worknumbers.Contains(t.WorkNumber)).ToListAsync();
            var userExtensions = await _dbPlatform.Queryable<UserExtension>()
        .Where(a => a.Status == "3" && worknumbers.Contains(a.Sapemployeeid))
        .ToListAsync();

            List<CourseTrainUserDetailEntity> courseTrainUserDetailEntities = new List<CourseTrainUserDetailEntity>();

            foreach (var worknumber in worknumbers)
            {
                CourseTrainUserDetailEntity courseTrainUserDetailEntity = new CourseTrainUserDetailEntity();
                var user = users.FirstOrDefault(t => t.WorkNumber == worknumber);

                if (courseTrainUserDetailEntities.Where(t => t.TrainUserWorknumber == user.WorkNumber).Count() == 0)
                {
                    var userExtension = userExtensions.FirstOrDefault(t => t.Sapemployeeid == worknumber);
                    courseTrainUserDetailEntity.TrainUserWorknumber = user?.WorkNumber;
                    courseTrainUserDetailEntity.TrainUser = user?.UserName;
                    courseTrainUserDetailEntity.DepartMent = user?.FullPathText;
                    courseTrainUserDetailEntity.DepartMentCode = user?.FullPathCode;
                    courseTrainUserDetailEntity.Rank = userExtension.Posnc;
                    courseTrainUserDetailEntities.Add(courseTrainUserDetailEntity);
                }
            }

            return courseTrainUserDetailEntities;
        }

        #endregion
        #region 境外来华

        /// <summary>
        /// 查询境外来华清单数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns>境外来华明细查询数据</returns>
        public async Task<PagedResultPowerDto<GetCourseAbToChinaOutput>> GetCourseAbToChinaList(GetCourseAbToChinaInput input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = _db.Queryable<CourseAbroadToChinaEntity>()
                  .WhereIF(!input.Company.IsNullOrEmpty(), t => t.Company.Contains(input.Company))
                  .WhereIF(!input.TrainUserName.IsNullOrEmpty(), t => t.TrainUserName.Contains(input.TrainUserName))
                  .WhereIF(!input.Duty.IsNullOrEmpty(), t => t.Duty.Contains(input.Duty))
                  .WhereIF(input.BeginTimeStart != null, t => input.BeginTimeStart <= t.EndTime)
                  .WhereIF(input.BeginTimeEnd != null, t => input.BeginTimeEnd >= t.EndTime)
                  .WhereIF(input.EndTimeEnd != null, t => input.EndTimeEnd <= t.BeginTime)
                  .WhereIF(input.EndTimeStart != null, t => input.EndTimeStart >= t.BeginTime)
                  .OrderBy(t => t.CreateTime, OrderByType.Desc)
                .Select(t =>
                    new GetCourseAbToChinaOutput()
                    {
                        AbroadId = t.AbroadId,
                        PassportInfo = t.PassportInfo,
                        TrainUserName = t.TrainUserName,
                        DepartMent = t.DepartMent,
                        Company = t.Company,
                        Duty = t.Duty,
                        BeginTime = t.BeginTime,
                        EndTime = t.EndTime,
                        AttchMentId = t.AttchMentId,
                        AttchMentName = t.AttchMentName,
                    });

            var listViewDto = await listQueryable.ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            //返回结果
            return new PagedResultPowerDto<GetCourseAbToChinaOutput>()
            {
                TotalCount = totalCount,
                Items = listViewDto
            };
        }

        /// <summary>
        /// 境外来华清单明细数据 导出数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<GetCourseAbToChinaOutput>> ExportCourseAbToChinaListAsync(GetCourseAbToChinaInput input)
        {
            var listQueryable = _db.Queryable<CourseAbroadToChinaEntity>()
                  .WhereIF(!input.Company.IsNullOrEmpty(), t => t.Company.Contains(input.Company))
                  .WhereIF(!input.TrainUserName.IsNullOrEmpty(), t => t.TrainUserName.Contains(input.TrainUserName))
                  .WhereIF(!input.Duty.IsNullOrEmpty(), t => t.Duty.Contains(input.Duty))
                  .WhereIF(input.BeginTimeStart != null, t => input.BeginTimeStart <= t.EndTime)
                  .WhereIF(input.BeginTimeEnd != null, t => input.BeginTimeEnd >= t.EndTime)
                  .WhereIF(input.EndTimeEnd != null, t => input.EndTimeEnd <= t.BeginTime)
                  .WhereIF(input.EndTimeStart != null, t => input.EndTimeStart >= t.BeginTime)
                  .OrderBy(t => t.CreateTime, OrderByType.Desc)
                .Select(t =>
                    new GetCourseAbToChinaOutput()
                    {
                        AbroadId = t.AbroadId,
                        PassportInfo = t.PassportInfo,
                        TrainUserName = t.TrainUserName,
                        DepartMent = t.DepartMent,
                        Company = t.Company,
                        Duty = t.Duty,
                        BeginTime = t.BeginTime,
                        EndTime = t.EndTime,
                        AttchMentId = t.AttchMentId,
                        AttchMentName = t.AttchMentName,
                    });
            return await listQueryable.ToListAsync();
        }

        /// <summary>
        /// 新增或者更新境外来华清单数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task AddOrUpdateCourseAbroadToChina(CourseAbroadToChinaEntity input)
        {
            input.CreateTime = DateTime.Now;
            input.CreateUserName = CurrentUser.UserName;
            input.WorkNumber = CurrentUser.Id.ToString();
            if (input.AbroadId.IsNullOrEmpty())
            {
                input.AbroadId = Guid.NewGuid().ToString();
                await _db.Insertable(input).ExecuteCommandAsync();
            }
            else
            {
                await _db.Updateable(input).ExecuteCommandAsync();
            }
        }

        /// <summary>
        /// 删除境外来华清单数据
        /// </summary>
        /// <param name="abroadId">主键</param>
        public async Task DeleteAbroadToChina(string abroadId)
        {
            await _db.Deleteable<CourseAbroadToChinaEntity>().Where(t => t.AbroadId == abroadId).ExecuteCommandAsync();
        }

        /// <summary>
        /// 导入海外来华任务数据
        /// </summary>
        /// <param data="导入数据"></param>
        /// <returns></returns>
        public async Task ImportAbroadUsersAsync(List<CourseAbroadToChinaEntity> data)
        {
            data.ForEach(t =>
            {
                t.AbroadId = Guid.NewGuid().ToString();
            });
            await _db.Insertable(data).ExecuteCommandAsync();
        }
        #endregion
        #region 项目页面

        /// <summary>
        /// 项目列表明细查询数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns>项目列表明细查询数据</returns>
        public async Task<PagedResultPowerDto<GetCourseProjectOutput>> GetCourseProjectList(GetCourseItemInput input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = _db.Queryable<CourseProjectEntity>()
                  .WhereIF(!input.Code.IsNullOrEmpty(), t => t.ProjectCode.Contains(input.Code))
                  .WhereIF(!input.Name.IsNullOrEmpty(), t => t.ProjectName.Contains(input.Name))
                   .OrderBy(t => t.ProjectCode, OrderByType.Asc)
                .Select(t =>
                    new GetCourseProjectOutput()
                    {
                        ProjectId = t.ProjectId,
                        ProjectCode = t.ProjectCode,
                        ProjectName = t.ProjectName,
                        Status = t.Status
                    });

            var listViewDto = await listQueryable.ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            //返回结果
            return new PagedResultPowerDto<GetCourseProjectOutput>()
            {
                TotalCount = totalCount,
                Items = listViewDto
            };
        }

        /// <summary>
        /// 新增或者更新培训项目数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task AddOrUpdateCourseProject(CourseProjectEntity input)
        {
            if (input.ProjectId.IsNullOrEmpty())
            {
                input.ProjectId = Guid.NewGuid().ToString();
                input.CreateDate = DateTime.Now;
                input.CreateUser = CurrentUser.UserName;
                input.CreateUser = CurrentUser.Id.ToString();
                input.Status = 1;

                int count = await _db.Queryable<CourseProjectEntity>().Where(t => t.ProjectCode == input.ProjectCode).CountAsync();

                if (count > 0)
                {
                    throw new Exception($"{input.ProjectCode}编码已存在！");
                }

                await _db.Insertable(input).ExecuteCommandAsync();
            }
            else
            {
                int count = await _db.Queryable<CourseProjectEntity>().Where(t => t.ProjectCode == input.ProjectCode && t.ProjectId != input.ProjectId).CountAsync();

                if (count > 0)
                {
                    throw new Exception($"{input.ProjectCode}编码已存在！");
                }

                await _db.Updateable(input).ExecuteCommandAsync();
            }
        }

        /// <summary>
        /// 更新培训项目状态
        /// </summary>
        /// <param name="courseProjectId">主键</param>
        /// <param name="status">状态</param>
        public async Task UpdateCourseProjectStatus(string courseProjectId, int status)
        {
            await _db.Updateable<CourseProjectEntity>().SetColumns(t => t.Status == status).Where(t => t.ProjectId == courseProjectId).ExecuteCommandAsync();
        }

        /// <summary>
        /// 删除培训项目数据
        /// </summary>
        /// <param name="courseProjectId">主键</param>
        public async Task DeleteCourseProject(string courseProjectId)
        {
            await _db.Deleteable<CourseProjectEntity>().Where(t => t.ProjectId == courseProjectId).ExecuteCommandAsync();
        }

        /// <summary>
        /// 培训项目数据 导出数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<GetCourseProjectOutput>> ExportCourseProjectResultAsync(GetCourseItemInput input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = _db.Queryable<CourseProjectEntity>()
                  .WhereIF(!input.Code.IsNullOrEmpty(), t => t.ProjectCode.Contains(input.Code))
                  .WhereIF(!input.Name.IsNullOrEmpty(), t => t.ProjectName.Contains(input.Name))
                  .OrderBy(t => t.ProjectCode, OrderByType.Asc)
                .Select(t =>
                    new GetCourseProjectOutput()
                    {
                        ProjectId = t.ProjectId,
                        ProjectCode = t.ProjectCode,
                        ProjectName = t.ProjectName,
                        Status = t.Status
                    });

            var listViewDto = await listQueryable.ToListAsync();

            //返回结果
            return listViewDto;
        }

        /// <summary>
        /// 获取项目下拉选项
        /// </summary>
        public async Task<List<ItemPairDto>> GetProjectOptions()
        {
            return await _db.Queryable<CourseProjectEntity>()
                .Where(t => t.Status == 1)
                 .OrderBy(t => t.ProjectCode, OrderByType.Asc)
                .Select(t => new ItemPairDto { Value = t.ProjectCode, Label = t.ProjectName })
                .ToListAsync();
        }

        #endregion
        #region 课程页面

        /// <summary>
        /// 课程列表明细查询数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns>课程列表明细查询数据</returns>
        public async Task<PagedResultPowerDto<GetCourseManageOutput>> GetCourseManageList(GetCourseItemInput input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = _db.Queryable<CourseManageEntity>()
                  .WhereIF(!input.Code.IsNullOrEmpty(), t => t.CourseCode.Contains(input.Code))
                  .WhereIF(!input.Name.IsNullOrEmpty(), t => t.CourseName.Contains(input.Name))
                  .OrderBy(t => t.CourseCode, OrderByType.Asc)
                .Select(t =>
                    new GetCourseManageOutput()
                    {
                        CourseId = t.CourseId,
                        CourseCode = t.CourseCode,
                        CourseName = t.CourseName,
                        Status = t.Status,
                        ProjectCode = t.ProjectCode,
                        ProjectName = t.ProjectName
                    });

            var listViewDto = await listQueryable.ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            //返回结果
            return new PagedResultPowerDto<GetCourseManageOutput>()
            {
                TotalCount = totalCount,
                Items = listViewDto
            };
        }

        /// <summary>
        /// 新增或者更新培训课程数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task AddOrUpdateCourseManage(CourseManageEntity input)
        {
            if (input.CourseId.IsNullOrEmpty())
            {
                input.CourseId = Guid.NewGuid().ToString();
                input.CreateDate = DateTime.Now;
                input.CreateUser = CurrentUser.UserName;
                input.CreateUser = CurrentUser.Id.ToString();
                input.Status = 1;

                int count = await _db.Queryable<CourseManageEntity>().Where(t => t.CourseCode == input.CourseCode).CountAsync();

                if (count > 0)
                {
                    throw new Exception($"{input.CourseCode}编码已存在！");
                }

                await _db.Insertable(input).ExecuteCommandAsync();
            }
            else
            {
                int count = await _db.Queryable<CourseManageEntity>().Where(t => t.CourseCode == input.CourseCode && t.CourseId != input.CourseId).CountAsync();

                if (count > 0)
                {
                    throw new Exception($"{input.CourseCode}编码已存在！");
                }

                await _db.Updateable(input).ExecuteCommandAsync();
            }
        }

        /// <summary>
        /// 更新培训课程状态
        /// </summary>
        /// <param name="CourseManageId">主键</param>
        /// <param name="status">状态</param>
        public async Task UpdateCourseManageStatus(string CourseManageId, int status)
        {
            await _db.Updateable<CourseManageEntity>().SetColumns(t => t.Status == status).Where(t => t.CourseId == CourseManageId).ExecuteCommandAsync();
        }

        /// <summary>
        /// 删除培训课程数据
        /// </summary>
        /// <param name="CourseManageId">主键</param>
        public async Task DeleteCourseManage(string CourseManageId)
        {
            await _db.Deleteable<CourseManageEntity>().Where(t => t.CourseId == CourseManageId).ExecuteCommandAsync();
        }

        /// <summary>
        /// 培训课程数据 导出数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<GetCourseManageOutput>> ExportCourseManageResultAsync(GetCourseItemInput input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = _db.Queryable<CourseManageEntity>()
                  .WhereIF(!input.Code.IsNullOrEmpty(), t => t.CourseCode.Contains(input.Code))
                  .WhereIF(!input.Name.IsNullOrEmpty(), t => t.CourseName.Contains(input.Name))
                  .OrderBy(t => t.CourseCode, OrderByType.Asc)
                .Select(t =>
                    new GetCourseManageOutput()
                    {
                        CourseId = t.CourseId,
                        CourseCode = t.CourseCode,
                        CourseName = t.CourseName,
                        Status = t.Status,
                        ProjectCode = t.ProjectCode,
                        ProjectName = t.ProjectName
                    });

            var listViewDto = await listQueryable.ToListAsync();

            //返回结果
            return listViewDto;
        }

        /// <summary>
        /// 获取课程下拉选项
        /// </summary>
        public async Task<List<ItemPairDto>> GetManageOptions()
        {
            return await _db.Queryable<CourseManageEntity>()
                .Where(t => t.Status == 1)
                .Select(t => new ItemPairDto { Value = t.CourseCode, Label = t.CourseName })
                .ToListAsync();
        }

        #endregion
        #region  同步Ilearning数据

        /// <summary>
        /// 根据iLearaning获取培训人员明细数据
        /// </summary>
        /// <param name="ilearningCodes">请求参数</param>
        /// <returns>培训人员明细列表</returns>
        public async Task<List<CourseTrainUserDetailEntity>> GetTrainUsers(List<string> ilearningCodes)
        {
            string token = await GetAccessTokenAsync();
            var headers = new Dictionary<string, string>
                {
                    { "Content-Type", "application/json" },
                    { "sourceSystem", "BPMNEW" },
                    { "serviceName", "	S_XXX_Ilearn_ilearninggetvisible_S" }
                };

            ILearningRequestDto<TrainSearchDto> learningRequest = new ILearningRequestDto<TrainSearchDto>() { Body = new TrainSearchDto() { }, Url = new ILearningToken { } };
            learningRequest.Url.AccessToken = token;
            learningRequest.Body.Page = 0;
            learningRequest.Body.PageSize = 200;
            List<CourseUserDto> trainingCourseDtos = new List<CourseUserDto>();
            ILearningResponseDto<List<CourseUserDto>> response = new ILearningResponseDto<List<CourseUserDto>>() { PageCount = 0 };

            foreach (var ilearningCode in ilearningCodes)
            {
                learningRequest.Body.TrainId = ilearningCodes.FirstOrDefault();
                response.PageCount = 0;
                while (response.PageCount > learningRequest.Body.Page || learningRequest.Body.Page == 0)
                {
                    learningRequest.Body.Page += 1;
                    response = await SyncCourseUsers(headers, learningRequest);
                    trainingCourseDtos.AddRange(response.Results);
                }
            }

            List<string> userLoginIds = trainingCourseDtos.Select(t => t.UserId).ToList();
            var users = await _dbPlatform.Queryable<Users>().Where(t => userLoginIds.Contains(t.UserLoginId)).ToListAsync();
            var userExtensions = await _dbPlatform.Queryable<UserExtension>()
            .Where(a => a.Status == "3" && userLoginIds.Contains(a.Loginname))
            .ToListAsync();

            List<CourseTrainUserDetailEntity> courseTrainUserDetailEntities = new List<CourseTrainUserDetailEntity>();

            foreach (var item in trainingCourseDtos)
            {
                CourseTrainUserDetailEntity courseTrainUserDetailEntity = new CourseTrainUserDetailEntity();
                var user = users.FirstOrDefault(t => t.UserLoginId.ToUpper() == item.UserId.ToUpper());

                // 本地不存在该用户，则不传送到前台
                if (user == null)
                {
                    continue;
                }

                if (courseTrainUserDetailEntities.Where(t => t.TrainUserWorknumber == user.WorkNumber).Count() == 0)
                {
                    var userExtension = userExtensions.FirstOrDefault(t => t.Loginname.ToUpper() == item.UserId.ToUpper());
                    courseTrainUserDetailEntity.TrainUserWorknumber = user?.WorkNumber;
                    courseTrainUserDetailEntity.TrainUser = user?.UserName;
                    courseTrainUserDetailEntity.DepartMent = user?.FullPathText;
                    courseTrainUserDetailEntity.DepartMentCode = user?.FullPathCode;
                    courseTrainUserDetailEntity.Rank = userExtension.Posnc;
                    courseTrainUserDetailEntities.Add(courseTrainUserDetailEntity);
                }
            }

            return courseTrainUserDetailEntities;
        }

        /// <summary>
        /// 获取ILearning选项
        /// </summary>
        /// <returns>任务单详情</returns>
        public async Task<List<ItemPairDto>> GetILearningOptions()
        {
            return await _db.Queryable<ILearningTrainEntity>().Select(t => new ItemPairDto { Value = t.TrainId.ToString(), Label = t.TrainName }).ToListAsync();
        }

        /// <summary>
        /// 同步iLearning课程信息
        /// </summary>
        /// <returns>是否成功</returns>
        public async Task<string> SyncTrainCourses(int times = 0)
        {
            string token = await GetAccessTokenAsync();
            var headers = new Dictionary<string, string>
                {
                    { "Content-Type", "application/json" },
                    { "sourceSystem", "BPMNEW" },
                    { "serviceName", "	S_XXX_Ilearn_ilearningtraininglist_S" }
                };

            TrainSearchDto learningRequest = new TrainSearchDto();
            learningRequest.AccessToken = token;
            learningRequest.Page = 0;
            learningRequest.PageSize = 100;
            List<TrainingCourseDto> trainingCourseDtos = new List<TrainingCourseDto>();
            var response = new ILearningResponseDto<List<TrainingCourseDto>>() { PageCount = 0 };
            while (response.PageCount > learningRequest.Page || learningRequest.Page == 0)
            {
                learningRequest.Page += 1;
                response = await SyncTrainCoursesGroup(headers, learningRequest);
                trainingCourseDtos.AddRange(response.Results);
            }

            List<ILearningTrainEntity> learningTrainEntities = new List<ILearningTrainEntity>();
            List<ILearningTrainCourseEntity> learningTrainCourseEntities = new List<ILearningTrainCourseEntity>();
            foreach (var couestDto in trainingCourseDtos)
            {
                ILearningTrainEntity ilearningTrain = new ILearningTrainEntity();
                ilearningTrain.TrainId = couestDto.TrainId;
                ilearningTrain.TrainName = couestDto.TrainName;
                ilearningTrain.Intro = couestDto.Intro;
                ilearningTrain.CategoryId = couestDto.CategoryId;
                ilearningTrain.CategoryName = couestDto.CategoryName;
                ilearningTrain.Image = couestDto.Image;
                ilearningTrain.CertificateId = couestDto.CertificateId;
                ilearningTrain.CertificateName = couestDto.CertificateName;
                ilearningTrain.StudyType = couestDto.StudyType;
                ilearningTrain.CreateTime = couestDto.CreateTime;
                ilearningTrain.StartTime = couestDto.StartTime;
                ilearningTrain.EndTime = couestDto.EndTime;
                ilearningTrain.Duration = couestDto.Duration;
                ilearningTrain.Points = couestDto.Points;
                ilearningTrain.Credit = couestDto.Credit;
                ilearningTrain.DisplayMode = couestDto.DisplayMode;
                ilearningTrain.PhaseType = couestDto.PhaseType;
                ilearningTrain.QuestionnaireId = couestDto.QuestionnaireId;
                ilearningTrain.QuestionnaireName = couestDto.QuestionnaireName;
                ilearningTrain.Creator = couestDto.Creator;
                ilearningTrain.CreatorName = couestDto.CreatorName;
                ilearningTrain.Archive = couestDto.Archive;
                ilearningTrain.H5Url = couestDto.H5Url;
                ilearningTrain.PcUrl = couestDto.PcUrl;
                var ilearningTrainCours = couestDto.ContentList.Select(t => new ILearningTrainCourseEntity()
                {
                    CourseDetailId = Guid.NewGuid().ToString(),
                    CourseId = t.Id,
                    TrainId = couestDto.TrainId,
                    CourseName = t.Name,
                    CourseType = t.ContentType,
                    StartTime = t.StartTime,
                    EndTime = t.EndTime

                }).ToList();

                learningTrainEntities.Add(ilearningTrain);
                learningTrainCourseEntities.AddRange(ilearningTrainCours);
            }

            await _db.Deleteable<ILearningTrainEntity>().ExecuteCommandAsync();
            await _db.Deleteable<ILearningTrainCourseEntity>().ExecuteCommandAsync();
            await _db.Insertable(learningTrainEntities).ExecuteCommandAsync();
            await _db.Insertable(learningTrainCourseEntities).ExecuteCommandAsync();

            return "success";
        }

        /// <summary>
        /// 同步iLearning讲师数据
        /// </summary>
        public async Task SyncInstractor()
        {
            string token = await GetAccessTokenAsync();
            var headers = new Dictionary<string, string>
                {
                    { "Content-Type", "application/json" },
                    { "sourceSystem", "BPMNEW" },
                    { "serviceName", "	S_XXX_Ilearn_ilearningTeacherList_S" }
                };

            ILearningRequestDto<TrainSearchDto> learningRequest = new ILearningRequestDto<TrainSearchDto>() { Url = new ILearningToken(), Body = new TrainSearchDto() };
            learningRequest.Url.AccessToken = token;
            learningRequest.Body.Page = 0;
            learningRequest.Body.PageSize = 100;
            List<InstractorDto> instractors = new List<InstractorDto>();
            var response = new ILearningResponseDto<List<InstractorDto>>() { PageCount = 0 };
            while (response.PageCount > learningRequest.Body.Page || learningRequest.Body.Page == 0)
            {
                learningRequest.Body.Page += 1;
                response = await SyncTrainIntructorGroup(headers, learningRequest);
                instractors.AddRange(response.Results);
            }

            List<CourseInstructorEntity> courseInstructorEntities = await _db.Queryable<CourseInstructorEntity>().ToListAsync();
            var result = instractors.GroupJoin(courseInstructorEntities, t => t.Id, c => c.InstructorCode,
                (t, c) => new CourseInstructorEntity
                {
                    Company = c.FirstOrDefault()?.Company,
                    CourseInstructorId = c.FirstOrDefault()?.CourseInstructorId,
                    InstructorCode = t.Id,
                    InstructorType = t.InstructorType,
                    InstructorName = t.Username,
                    CreateDate = t.DateTime,
                    UserId = t.UserId ?? "外部讲师",
                    CoursePeriod = c.FirstOrDefault()?.CoursePeriod
                }).ToList();

            var userIds = instractors.Select(t => t.UserId).ToList();
            var users = await _dbPlatform.Queryable<Users>().Where(t => userIds.Contains(t.UserLoginId)).ToListAsync();
            foreach (var item in result)
            {
                item.CourseInstructorId = Guid.NewGuid().ToString();
                item.CreateUser = "admin";
                item.CreateWorkNumber = "99999999";
                item.Status = 1;

                if (item.InstructorType == "内部讲师")
                {
                    Users user = users.FirstOrDefault(t => t.UserLoginId.ToUpper() == item.UserId.ToUpper());
                    item.Company = user?.FullPathText;
                    item.WorkNumber = user?.WorkNumber;
                }
            }

            await _db.Deleteable<CourseInstructorEntity>().ExecuteCommandAsync();
            await _db.Insertable(result).ExecuteCommandAsync();
        }
        #endregion

        #region 报表
        /// <summary>
        /// 国内培训计划流程表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultPowerDto<ExportCourseOutput>> GetReportResult(CourseReportDto.ReportSearchDto input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = new List<ExportCourseOutput>();
            listQueryable = await _db.Queryable<CourseTrainEntity>()
                .WhereIF(!input.InstanceNumber.IsNullOrEmpty(), t => t.InstanceNumber == input.InstanceNumber)
                .WhereIF(!input.WorkNumber.IsNullOrEmpty(), t => t.WorkNumber.Contains(input.WorkNumber))
                .WhereIF(!input.UserName.IsNullOrEmpty(), t => t.CreateUserName.Contains(input.UserName))
                .WhereIF(!input.ProjectName.IsNullOrEmpty(), t => t.ProjectName.Contains(input.ProjectName))
                //.WhereIF(!role.Item1, (c, t, d) => SqlFunc.ContainsArray(role.Item2, t.WorkNumber))
                .OrderBy(t => t.CreateTime, OrderByType.Desc)
                .Select(t => new ExportCourseOutput
                {
                    InstanceNumber = t.InstanceNumber,
                    StatusName = t.StatusName,
                    WorkNumber = t.WorkNumber,
                    UserName = t.CreateUserName,
                    Company = t.Company,
                    Department = t.Department,
                    TrainDate = t.TrainDate,
                    ProjectName = t.ProjectName,
                    TrainBudget = t.TrainBudget,
                    TrainUserNumber = t.TrainUserNumber,
                    MealFrequency = t.MealFrequency
                })
           .ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            //返回结果
            return new PagedResultPowerDto<ExportCourseOutput>()
            {
                TotalCount = totalCount,
                Items = listQueryable
            };
        }

        /// <summary>
        /// 报销费用统计表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultPowerDto<CourseTrainTaskReportDto>> GetExpenseReportResult(CourseReportDto.ReportSearchDto input)
        {
            RefAsync<int> totalCount = 0;

            var listQueryable = new List<CourseTrainTaskReportDto>();
            listQueryable = await _db.Queryable<CourseTrainTaskEntity>()
                .WhereIF(!input.InstanceNumber.IsNullOrEmpty(), t => t.InstanceNumber == input.InstanceNumber)
                .WhereIF(!input.WorkNumber.IsNullOrEmpty(), t => t.WorkNumber.Contains(input.WorkNumber))
                .WhereIF(!input.UserName.IsNullOrEmpty(), t => t.CreateUserName.Contains(input.UserName))
                .WhereIF(!input.ProjectName.IsNullOrEmpty(), t => t.TraningProject.Contains(input.ProjectName))
                .OrderBy(t => t.CourseTrainCode, OrderByType.Desc)
                .Select(t => new CourseTrainTaskReportDto { })
           .ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            //返回结果
            return new PagedResultPowerDto<CourseTrainTaskReportDto>()
            {
                TotalCount = totalCount,
                Items = listQueryable
            };
        }
        #endregion
        #region 私有方法

        /// <summary>
        /// 检查国内培训任务单
        /// </summary>
        /// <param name="data">培训任务单数据</param>
        /// <returns></returns>
        private (bool Result, string Msg) CheckTrainTask(CourseTrainTaskDto data)
        {
            StringBuilder errorMsg = new StringBuilder();
            //if (data.BaseData.CourseBeginTime.IsNullOrEmpty())
            //{
            //    errorMsg.Append("授课开始时间不能为空!</br>");
            //}
            //if (data.BaseData.CourseEndTime.IsNullOrEmpty())
            //{
            //    errorMsg.Append("授课结束时间不能为空!</br>");
            //}
            if (data.BaseData.CourseAddress.IsNullOrEmpty())
            {
                errorMsg.Append("授课地址不能为空!</br>");
            }
            if (data.BaseData.OrgCost1 == null)
            {
                errorMsg.Append("杂费不能为空!</br>");
            }
            if (data.BaseData.OrgCost2 == null)
            {
                errorMsg.Append("餐费不能为空!</br>");
            }
            if (data.BaseData.OrgCost3 == null)
            {
                errorMsg.Append("差旅费不能为空!</br>");
            }

            //if (data.BaseData.OrgCost4 == null)
            //{
            //    errorMsg.Append("组织费用4不能为空!</br>");
            //}
            //if (data.BaseData.OrgCost5 == null)
            //{
            //    errorMsg.Append("组织费用5不能为空!</br>");
            //}
            //if (data.BaseData.OrgCost6 == null)
            //{
            //    errorMsg.Append("组织费用6不能为空!</br>");
            //}
            //if (data.BaseData.ActrualUsers == null)
            //{
            //    errorMsg.Append("实际听课人数不能为空!</br>");
            //}
            //if (data.BaseData.HotelFee == null)
            //{
            //    errorMsg.Append("住宿费用不能为空!</br>");
            //}
            //if (data.BaseData.TransportFee == null)
            //{
            //    errorMsg.Append("交通费不能为空!</br>");
            //}
            //if (data.BaseData.SubsideFee == null)
            //{
            //    errorMsg.Append("津贴不能为空!</br>");
            //}
            //if (data.BaseData.ShareFee == null)
            //{
            //    errorMsg.Append("分摊费用不能为空!</br>");
            //}
            //if (data.BaseData.CourseFee == null)
            //{
            //    errorMsg.Append("课程费用不能为空!</br>");
            //}
            //if (!data.ILearningList.Any())
            //{
            //    errorMsg.Append("请选择iLearning关联数据!</br>");
            //}
            if (!data.TrainUserList.Any())
            {
                errorMsg.Append("请导入/同步/新增参训人员数据!</br>");
            }
            if (!data.PointAllocateList.Any())
            {
                errorMsg.Append("请选择分配课时!</br>");
            }
            else
            {
                int i = 1;
                data.PointAllocateList.ForEach(t =>
                {
                    if (t.InstructorName.IsNullOrEmpty())
                    {
                        errorMsg.Append($"请为第{i}行课时分配明细选择讲师!</br>");
                    }

                    i++;
                });
            }

            return (errorMsg.Length == 0, errorMsg.ToString());
        }

        /// <summary>
        /// 同步培训用户
        /// </summary>
        /// <param name="headers">请求头</param>
        /// <param name="learningRequest">请求消息</param>
        /// <param name="times">重试次数</param>
        /// <returns></returns>
        private async Task<ILearningResponseDto<List<CourseUserDto>>> SyncCourseUsers(Dictionary<string, string> headers, ILearningRequestDto<TrainSearchDto> learningRequest, int times = 0)
        {
            if (times > 3)
            {
                throw new ApplicationException("请求异常！");
            }

            string response = await _nPRestHttp.ESBPostAsync(_esbWebApiUrl + "/body", JsonConvert.SerializeObject(learningRequest, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }), headers);
            ILearningResponseDto<List<CourseUserDto>> learningResponse = JsonConvert.DeserializeObject<ILearningResponseDto<List<CourseUserDto>>>(response);

            if (learningResponse.ErrorCode == 0)
            {
                return learningResponse;
            }
            else if (learningResponse.ErrorCode == 401)
            {

            }
            else if (learningResponse.ErrorCode == 429)
            {
                System.Threading.Thread.Sleep(60000);
                return await SyncCourseUsers(headers, learningRequest, times);
            }

            return new ILearningResponseDto<List<CourseUserDto>>();
        }

        /// <summary>
        /// 同步课程信息
        /// </summary>
        /// <param name="headers">请求头</param>
        /// <param name="learningRequest">请求数据</param>
        /// <param name="times">重试次数</param>
        /// <returns></returns>
        /// <exception cref="ApplicationException"></exception>
        private async Task<ILearningResponseDto<List<TrainingCourseDto>>> SyncTrainCoursesGroup(Dictionary<string, string> headers, TrainSearchDto learningRequest, int times = 0)
        {
            if (times > 3)
            {
                throw new ApplicationException("请求异常！");
            }

            string response = await _nPRestHttp.ESBPostAsync(_esbWebApiUrl, JsonConvert.SerializeObject(learningRequest, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }), headers);
            ILearningResponseDto<List<TrainingCourseDto>> learningResponse = JsonConvert.DeserializeObject<ILearningResponseDto<List<TrainingCourseDto>>>(response);

            if (learningResponse.ErrorCode == 0)
            {
                return learningResponse;
            }
            else if (learningResponse.ErrorCode == 401)
            {
                times++;
            }
            else if (learningResponse.ErrorCode == 429)
            {
                times++;
                System.Threading.Thread.Sleep(60000);
                return await SyncTrainCoursesGroup(headers, learningRequest, times);
            }

            return new ILearningResponseDto<List<TrainingCourseDto>>();
        }

        /// <summary>
        /// 同步讲师信息
        /// </summary>
        /// <param name="headers">请求头</param>
        /// <param name="learningRequest">请求数据</param>
        /// <param name="times">重试次数</param>
        /// <returns></returns>
        /// <exception cref="ApplicationException"></exception>
        private async Task<ILearningResponseDto<List<InstractorDto>>> SyncTrainIntructorGroup(Dictionary<string, string> headers, ILearningRequestDto<TrainSearchDto> learningRequest, int times = 0)
        {
            if (times > 3)
            {
                throw new ApplicationException("请求异常！");
            }

            string response = await _nPRestHttp.ESBPostAsync(_esbWebApiUrl + "/body", JsonConvert.SerializeObject(learningRequest, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }), headers);
            ILearningResponseDto<List<InstractorDto>> learningResponse = JsonConvert.DeserializeObject<ILearningResponseDto<List<InstractorDto>>>(response);

            if (learningResponse.ErrorCode == 0)
            {
                return learningResponse;
            }
            else if (learningResponse.ErrorCode == 401)
            {
                times++;
            }
            else if (learningResponse.ErrorCode == 429)
            {
                times++;
                System.Threading.Thread.Sleep(60000);
                return await SyncTrainIntructorGroup(headers, learningRequest, times);
            }

            return new ILearningResponseDto<List<InstractorDto>>();
        }

        /// <summary>
        /// 获取token
        /// </summary>
        /// <returns>token</returns>
        private async Task<string> GetAccessTokenAsync()
        {
            var headers = new Dictionary<string, string>
                {
                    { "Content-Type", "application/json" },
                    { "sourceSystem", "BPMNEW" },
                    { "serviceName", "	S_XXX_Ilearn_ilearningToken_S" }
                };

            string sendData = "{\"corpid\":\"" + _corpid + "\",\"corpsecret\":\"" + _corpsecret + "\"}";

            string token = await _nPRestHttp.ESBPostAsync(_esbWebApiUrl, sendData, headers);

            ILearningResponseDto<ILearningTokenDto> learningResponseDto = JsonConvert.DeserializeObject<ILearningResponseDto<ILearningTokenDto>>(token);

            if (learningResponseDto.ErrorCode == 0)
            {
                token = learningResponseDto.Results.AccessToken;

            }

            return token;
        }

        /// <summary>
        /// 获取用户权限
        /// </summary>
        /// <returns></returns>
        private Tuple<bool, bool, bool, List<string>> getUserRoles(string currentWorkNumber)
        {
            // 权限过滤
            var deptcodes = _dbPlatform.Queryable<SFPositionUserRelEntity, SFApproverEntity>((a, b) => a.PositionCode == b.PositionCode)
            .Where((a, b) => a.UserId == currentWorkNumber && (b.RoleCode == "HRBP TD DOA" || b.RoleCode == "ADMIN TD DOA")).Select((a, b) => new { a.UserId, b.DeptCode, b.RoleCode }).ToList();

            bool ishrBP = deptcodes.Count() > 0; // 是否是培训专员

            List<string> userCodes = new List<string>();
            if (ishrBP)
            {
                userCodes = _commonService.GetUserByRoleFilter(currentWorkNumber, RelationshipTypeEnum.培训专员, true);
            }

            userCodes = userCodes != null && userCodes.Count > 0 ? userCodes : new List<string>() { "-1" };
            bool isAdmin = false;
            var adminroles = _dbPlatform.Queryable<Dictionaries>()
                 .Where(t => t.TypeCode == "ADMINROLE").Select(t => t.Value).ToList();
            if (adminroles.Contains(currentWorkNumber))
            {
                isAdmin = true;
            }

            return new Tuple<bool, bool, bool, List<string>>(isAdmin, ishrBP, false, userCodes.Distinct().ToList());
        }
        #endregion
    }
}